<template>
  <div>
    <el-drawer v-bind="$attrs" v-on="$listeners" @opened="onOpen" @close="onClose">
      <div style="height:100%">
        <el-row style="height:100%">
          <el-col :md="24" :lg="24" class="right-preview">
            <iframe v-show="isIframeLoaded" ref="previewPage" class="result-wrapper" frameborder="0" src="preview.html"
              @load="iframeLoad" />

            <div v-show="!isIframeLoaded" v-loading="true" class="result-wrapper" />
          </el-col>
        </el-row>
      </div>

      <div v-show="activeTab==='html'" id="editorHtml" class="tab-editor" />
      <div v-show="activeTab==='js'" id="editorJs" class="tab-editor" />
      <div v-show="activeTab==='css'" id="editorCss" class="tab-editor" />
    </el-drawer>
  </div>
</template>
<script>
  import {
    parse
  } from '@babel/parser'
  import ClipboardJS from 'clipboard'
  import {
    saveAs
  } from 'file-saver'
  import {
    makeUpHtml,
    vueTemplate,
    vueScript,
    cssStyle
  } from '@/components/generator/html'
  import {
    makeUpJs
  } from '@/components/generator/js'
  import {
    makeUpCss
  } from '@/components/generator/css'
  import {
    exportDefault,
    beautifierConf,
    titleCase
  } from '@/utils/index'
  // import loadMonaco from '@/utils/loadMonaco'
  // import loadBeautifier from '@/utils/loadBeautifier'

  const editorObj = {
    html: null,
    js: null,
    css: null
  }
  const mode = {
    html: 'html',
    js: 'javascript',
    css: 'css'
  }

  let beautifier
  import * as monaco from 'monaco-editor/esm/vs/editor/editor.main.js';
  import 'monaco-editor/esm/vs/nls.js';

  export default {
    name: 'FormShow',
    components: {

    },
    props: ['formData', 'generateConf', 'onlyPreview'],
    data() {
      return {
        activeTab: '',
        htmlCode: '',
        jsCode: '',
        cssCode: '',
        codeFrame: '',
        isIframeLoaded: false,
        isInitcode: false, // 保证open后两个异步只执行一次runcode
        isRefreshCode: false, // 每次打开都需要重新刷新代码
        resourceVisible: false,
        scripts: [],
        links: [],
        monaco: null
      }
    },
    computed: {
      resources() {
        return this.scripts.concat(this.links)
      }
    },
    watch: {},
    created() {},
    mounted() {

    },
    beforeDestroy() {

    },
    methods: {
      onOpen() {
        const {
          type
        } = this.generateConf

        this.htmlCode = makeUpHtml(this.formData, type)
        this.jsCode = makeUpJs(this.formData, type)
        this.cssCode = makeUpCss(this.formData)

        beautifier = require('js-beautify')
        this.htmlCode = beautifier.html(this.htmlCode, beautifierConf.html)
        this.jsCode = beautifier.js(this.jsCode, beautifierConf.js)
        this.cssCode = beautifier.css(this.cssCode, beautifierConf.html)

        this.setEditorValue('editorHtml', 'html', this.htmlCode)
        this.setEditorValue('editorJs', 'js', this.jsCode)
        this.setEditorValue('editorCss', 'css', this.cssCode)

        if (!this.isInitcode) {
          this.isRefreshCode = true
          this.isIframeLoaded && (this.isInitcode = true) && this.runCode()
        }
      },

      onClose() {
        this.isInitcode = false
        this.isRefreshCode = false
      },

      iframeLoad() {
        if (!this.isInitcode) {
          this.isIframeLoaded = true
          this.isRefreshCode && (this.isInitcode = true) && this.runCode()
        }
      },

      setEditorValue(id, type, codeStr) {
        if (editorObj[type]) {
          editorObj[type].setValue(codeStr)
        } else {
          editorObj[type] = monaco.editor.create(document.getElementById(id), {
            value: codeStr,
            theme: 'vs-dark',
            language: mode[type],
            automaticLayout: true
          })
        }
        // ctrl + s 刷新
        editorObj[type].onKeyDown(e => {
          if (e.keyCode === 49 && (e.metaKey || e.ctrlKey)) {
            this.runCode()
          }
        })
      },

      runCode() {
        const jsCodeStr = editorObj.js.getValue()
        try {
          const ast = parse(jsCodeStr, {
            sourceType: 'module'
          })
          const astBody = ast.program.body
          if (astBody.length > 1) {
            this.$confirm(
              'js格式不能识别，仅支持修改export default的对象内容',
              '提示', {
                type: 'warning'
              }
            )
            return
          }
          if (astBody[0].type === 'ExportDefaultDeclaration') {
            const postData = {
              type: 'refreshFrame',
              data: {
                generateConf: this.generateConf,
                html: editorObj.html.getValue(),
                js: jsCodeStr.replace(exportDefault, ''),
                css: editorObj.css.getValue(),
                scripts: this.scripts,
                links: this.links
              }
            }

            this.$refs.previewPage.contentWindow.postMessage(
              postData,
              location.origin
            )
          } else {
            this.$message.error('请使用export default')
          }
        } catch (err) {
          this.$message.error(`js错误：${err}`)
          console.error(err)
        }
      }
    }
  }
</script>

<style lang="scss" scoped>
  @import '@/styles/mixin.scss';

  .tab-editor {
    position: absolute;
    top: 33px;
    bottom: 0;
    left: 0;
    right: 0;
    font-size: 14px;
  }

  .left-editor {
    position: relative;
    height: 100%;
    background: #1e1e1e;
    overflow: hidden;
  }

  .setting {
    position: absolute;
    right: 15px;
    top: 3px;
    color: #a9f122;
    font-size: 18px;
    cursor: pointer;
    z-index: 1;
  }

  .right-preview {
    height: 100%;

    .result-wrapper {
      height: calc(100vh - 33px);
      width: 100%;
      overflow: auto;
      padding: 12px;
      box-sizing: border-box;
    }
  }

  @include action-bar;

  ::v-deep .el-drawer__header {
    display: none;
  }
</style>
